//
//  QRCoedTool.swift
//  01-读取二维码
//
//  Created by xmg on 16/5/22.
//  Copyright © 2016年 xiao_kl. All rights reserved.
//

import UIKit
import CoreImage
import AVFoundation

typealias scanResultBlock = (resultStrs:[String])->()
class QRCoedTool :NSObject {
    
    //二维码工具单例
    static let shareQRCoedTool = QRCoedTool()
    
    //输入对象
    private lazy var input : AVCaptureDeviceInput? = {
        // 1. 获取摄像头设备
        // 1.1 把摄像头当做一个输入设备
       let device = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
        var input : AVCaptureDeviceInput?
        do {
            input = try AVCaptureDeviceInput(device: device)
        }catch {
            print("--------------\(error)")
            return nil
        }
        return input
    }()
    
    //输出对象
    private lazy var output : AVCaptureMetadataOutput = {
        //创建一个(元数据)输入处理对象
        let output = AVCaptureMetadataOutput()
        //设置代理,代理方法可以拿到处理结果
        output.setMetadataObjectsDelegate(self, queue: dispatch_get_main_queue())
        return output
    }()
    
    //创建一个会话,主要连接输入和输出
    private let session : AVCaptureSession = AVCaptureSession()
    
    //引用当前的视频预览图层
    private weak var layer: AVCaptureVideoPreviewLayer?
    
    private var resultBlock : scanResultBlock?

    
    /**
     假如要给二维码中心添加头像可以选择自定义二维码之后把中心图片传进来
    */
    class func createQRCoed(contentString : String , isCustomQRCoed : Bool , centerImage:UIImage?) ->UIImage?{
        
        let textStr = contentString
        
        //1开启滤镜
        let filter = CIFilter(name: "CIQRCodeGenerator")
        
        //1.1回复滤镜默认值
        filter?.setDefaults()
        
        //2.0设置滤镜的输入内容
        let data = textStr.dataUsingEncoding(NSUTF8StringEncoding)
        filter?.setValue(data, forKey: "inputMessage")
        //设置纠错率
        filter?.setValue("H", forKey: "inputCorrectionLevel")
        
        //3.从滤镜中取出图片
        guard let outImage = filter?.outputImage else {
            return nil
        }
        //图片放大
        let transform = CGAffineTransformMakeScale(10, 10)
        let transFormImage = outImage.imageByApplyingTransform(transform)
        
        //显示结果
        if isCustomQRCoed  {
            if centerImage != nil {
                
                return self.createImage(UIImage(CIImage: transFormImage), centerImage:centerImage!)
            }
            
        }
            
        return UIImage(CIImage: transFormImage)
        
        
   
    }
    
    /**
     给定一个二维码图片,识别二维码返回二维码的信息
     如果想要给识别到的二维码的图片加上边框可以参数写true
     */
    class func detectorQRCode(QRCodeImage:UIImage ,isAddBounds:Bool) ->(message:[String],resultImage:UIImage?){
        
        //创建一个二维码探测器
        /**
        第一个参数:选择扫描什么类型,有二维码,脸部识别
        第二个参数:是环境,可以nil
        第三个是扫描精确度:,value为精确度
        */
        let detector = CIDetector(ofType: CIDetectorTypeQRCode, context: nil, options: [CIDetectorAccuracy:CIDetectorAccuracyHigh])

        let imageCI = CIImage(image: QRCodeImage)
        let features = detector.featuresInImage(imageCI!)
        
        var resultStrs = [String]()
        var resultImage = QRCodeImage
        for feature in features {
            
            if feature.isKindOfClass(CIQRCodeFeature) {
                let CIQRCodeF = feature as! CIQRCodeFeature
                resultStrs.append(CIQRCodeF.messageString)
                //判断是否要添加边框
                if isAddBounds {
                    
                    resultImage = self.drawQRCodeFrame(resultImage, feature: CIQRCodeF)
                }
                
            }
        }
        
        if isAddBounds {
            return (resultStrs,resultImage)
        }
        
        return (resultStrs,nil)

        
    }
    
    
    /**
     利用摄像头扫描二维码
     第一个参数:把摄像头预览图层添加到那个View
     第二个参数:传一个闭包进来,闭包的参数就是扫描到的数据
     第三个参数:是否要添加兴趣区域
     第四个参数:感兴趣的区域
     */
    func scan(view:UIView ,result:scanResultBlock,isAddInterest:Bool,interestFrame:CGRect?) {
        
        self.resultBlock = result
        //获取输入设备
   
        
        //判断输入对象是否生成成功
        if self.input != nil {
            //容错处理,添加过就不需要再添加
            if self.session.canAddInput(input)&&self.session.canAddOutput(output) {
                self.session.addInput(input)
                self.session.addOutput(output)
            }
        }else{
            return
        }
       
        //设置元数据输出处理对象,处理数据的类型
        //处理所有支持的类型 output.
        //注意这一行代码只可以卸载这里,输入对象添加到会话之后
        output.metadataObjectTypes = [AVMetadataObjectTypeQRCode]
        
        //开启会话
        self.session.startRunning()
        
        //添加视频预览图层
        if self.layer != nil {
            
            self.layer = AVCaptureVideoPreviewLayer(session: self.session)
        }
        self.layer?.frame = view.bounds
        
        view.layer.insertSublayer(self.layer!, atIndex: 0)
    
        //设置输出的感兴趣位置
        if isAddInterest {
            if interestFrame != nil {
                
                let size = UIScreen.mainScreen().bounds.size
                let x : CGFloat = interestFrame!.origin.x / size.width
                let y : CGFloat = interestFrame!.origin.y / size.height
                let width : CGFloat = interestFrame!.origin.x / size.width
                let height : CGFloat = interestFrame!.size.height / size.height
                
                output.rectOfInterest = CGRect(x: x, y: y, width: width, height: height)
            }
        }
    }
    
}

extension QRCoedTool {
    //自定义二维码
    private class func createImage(sourecImage : UIImage ,centerImage : UIImage) -> UIImage {
        //开启上下文
        UIGraphicsBeginImageContextWithOptions(centerImage.size, false, UIScreen.mainScreen().scale)
        let rect = CGRectMake(0, 0, centerImage.size.width, centerImage.size.height)
        
        let path = UIBezierPath(ovalInRect: rect)
        path.addClip()
        //绘制图片
        centerImage.drawInRect(rect)
        
        //获取图片
        let resultCenterImage = UIGraphicsGetImageFromCurrentImageContext()
        
        //关闭上下文
        UIGraphicsEndImageContext()
        
        
        
        //开启上下文
        UIGraphicsBeginImageContextWithOptions(sourecImage.size, false, UIScreen.mainScreen().scale)
        
        //绘制图片
        sourecImage.drawInRect(CGRectMake(0, 0, sourecImage.size.width, sourecImage.size.height))
        
        let centerImageWH : CGFloat = 50
        let centerImageX : CGFloat = (sourecImage.size.width - centerImageWH) * 0.5
        let centerImageY : CGFloat = (sourecImage.size.height - centerImageWH) * 0.5
        resultCenterImage.drawInRect(CGRectMake(centerImageX, centerImageY, centerImageWH, centerImageWH))
        
        //获取图片
        let resultImage = UIGraphicsGetImageFromCurrentImageContext()
        
        //关闭上下文
        UIGraphicsEndImageContext()
        
        return resultImage
        
    }
    
    //标记扫描正确的二维码
    private class func drawQRCodeFrame(souresImage:UIImage,feature:CIFeature) ->UIImage{
        
        //开启上下文
        UIGraphicsBeginImageContextWithOptions(souresImage.size, false, UIScreen.mainScreen().scale)
        
        souresImage.drawInRect(CGRectMake(0, 0, souresImage.size.width, souresImage.size.height))
        
        //获取上下文
        let context = UIGraphicsGetCurrentContext()
        //上下文绕x轴翻转
        CGContextScaleCTM(context, 1, -1)
        //向下移动一个高度
        CGContextTranslateCTM(context, 0, -souresImage.size.height)
        
        
        
        let CIQRCodeF = feature as! CIQRCodeFeature
        let path = UIBezierPath(rect: CIQRCodeF.bounds)
        path.lineWidth = 5
        UIColor.greenColor().setStroke()
        path.stroke()
        
        
        let resultImage = UIGraphicsGetImageFromCurrentImageContext()
        
        UIGraphicsEndImageContext()
        
        return resultImage
        
    }
}



extension QRCoedTool : AVCaptureMetadataOutputObjectsDelegate {
    
    /**
     第一个参数:输出设备
     第二个参数:返回的内容
     */
    func captureOutput(captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [AnyObject]!, fromConnection connection: AVCaptureConnection!) {
        
        //移除之前的标记框
        self.removeQRCodeFrame()
        //记录结果
        var resultStrs : [String] = [String]()
        for metadata in metadataObjects {
            if metadata.isKindOfClass(AVMetadataMachineReadableCodeObject){
                //就是把坐标转换成为在layer层上面的真实坐标
                let transformObj = self.layer?.transformedMetadataObjectForMetadataObject(metadata as! AVMetadataObject)
                //把类转化为真实类型
                let qrCodeObj = transformObj as! AVMetadataMachineReadableCodeObject
                
                resultStrs.append(qrCodeObj.stringValue)
                //给扫描到的二维码添加边框
                //conrners:二维码的四个角
                self.drawQRCoreFrame(qrCodeObj)
                
                
                
            }
        }
        if self.resultBlock != nil {
            
            self.resultBlock!(resultStrs:resultStrs)
        }
    }
    
    func drawQRCoreFrame(QRCoreObj:AVMetadataMachineReadableCodeObject){
        //创建图形图层
        let shapLayer = CAShapeLayer()
        shapLayer.fillColor = UIColor.clearColor().CGColor
        shapLayer.strokeColor = UIColor.redColor().CGColor
        shapLayer.lineWidth = 5
        
        //给layer设置一个形状路劲,
        let corners = QRCoreObj.corners
        let path = UIBezierPath()
        var index = 0
        for corner in corners {
            
            var point = CGPointZero
            CGPointMakeWithDictionaryRepresentation(corner as! CFDictionary, &point)
            if index == 0 {
                path.moveToPoint(point)
            }else{
                path.addLineToPoint(point)
            }
            
            index += 1
            
        }
        //关闭路劲
        path.closePath()
        //给layer的path赋值
        shapLayer.path = path.CGPath
        //添加到图层
        self.layer?.addSublayer(shapLayer)
        
    }
    
    //移除之前的红色边框
    func removeQRCodeFrame(){
        guard let subLayers = self.layer?.sublayers else {
            return
        }
        for subLayer in subLayers {
            if subLayer.isKindOfClass(CAShapeLayer){
                subLayer.removeFromSuperlayer()
            }
        }
    }
    
}
